import form from './tui-validation'
Component({
  properties: {
    //表单数据对象
    model: {
      type: Object,
      value: {}
    },
    //表单验证规则，如果含有自定义校验规则请在校验方法中传入此参数
    rules: {
      type: Array,
      value: []
    },
    //表单背景颜色
    backgroundColor: {
      type: String,
      value: 'transparent'
    },
    //表单padding值
    padding: {
      type: String,
      value: '0'
    },
    //是否顶部弹出方式显示校验错误信息【为false时则可关联FormItem组件显示校验错误信息】
    showMessage: {
      type: Boolean,
      value: true,
      observer(val) {
        const children = this.data.childrenArr
        if (children && children.length > 0) {
          children.forEach(item => {
            item.setData({
              showError: val ? false : true
            })
          })
        }
      }
    },
    //表单圆角值
    radius: {
      type: String,
      value: '0'
    },
    //是否禁用该表单内的所有组件,透明遮罩层
    disabled: {
      type: Boolean,
      value: false
    },
    //提示框top值 px
    tipTop: {
      type: String,
      optionalTypes: [Number],
      value: 0
    },
    //错误提示框padding值
    tipPadding: {
      type: String,
      value: '20rpx'
    },
    //错误提示框背景色
    tipBackgroundColor: {
      type: String,
      value: ''
    },
    //错误提示字体大小
    tipSize: {
      type: String,
      optionalTypes: [Number],
      value: 28
    },
    //错误提示字体颜色
    tipColor: {
      type: String,
      value: '#fff'
    },
    //错误提示框圆角值
    tipRidus: {
      type: String,
      value: '12rpx'
    },
    //错误消息显示时间 ms
    duration: {
      type: String,
      optionalTypes: [Number],
      value: 0
    }
  },
  relations: {
    '../tui-form-item/tui-form-item': {
      type: 'descendant'
    }
  },
  data: {
    errorMsg: '',
    timer: null,
    g_tipBackgroundColor: (wx.$tui && wx.$tui.tuiForm.tipBackgroundColor) || '#f74d54',
    childrenArr: [],
    formRules: [],
    isImmediate: false,
    concatRules: []
  },
  lifetimes: {
    detached: function () {
      this.clearTimer()
    }
  },
  methods: {
    clearTimer() {
      clearTimeout(this.data.timer)
      this.data.timer = null;
      this.data.childrenArr = null
    },
    getFormItemRules() {
      let rules = []
      const children = this.data.childrenArr || []
      if (children.length > 0) {
        children.forEach(child => {
          let rule = child.getRules()
          rule && rules.push(rule)
        })
      }
      return rules;
    },
    getMergeRules(rules) {
      if (this.data.concatRules.length === 0) return rules;
      let formRules = [...rules]
      //合并并替换当前rules数据
      this.data.concatRules.forEach(item => {
        const index = rules.findIndex(e => e.name === item.name)
        if (index === -1) {
          formRules.push(item)
        } else {
          formRules[index] = item;
        }
      })
      return formRules;
    },
    //props中嵌套传入Function函数会丢失，model和rules参数由props传入改为校验方法validate中传入
    //{Object} model 表单数据对象，传null则使用属性中model值
    //{Array} rules 表单验证规则，传null则使用FormItem项内传入的rules值
    //{Boolean} checkAll 是否返回所有错误信息
    validate(model, rules, checkAll = false) {
      model = model || this.data.model
      rules = rules || this.data.rules
      const duration = this.data.duration || (wx.$tui && wx.$tui.tuiForm.duration) || 2000;
      return new Promise((resolve, reject) => {
        try {
          if (rules.length === 0) {
            rules = this.getFormItemRules()
          } else {
            rules = this.getMergeRules(rules)
          }
          let res = form.validation(model, rules, checkAll);
          if (!res.isPass) {
            let errors = res.errorMsg;
            if (this.data.showMessage) {
              this.clearTimer()
              if (checkAll) {
                errors = errors[0].msg
              }
              this.setData({
                errorMsg: errors
              })
              this.data.timer = setTimeout(() => {
                this.setData({
                  errorMsg: ''
                })
              }, Number(duration))
            } else {
              const children = this.data.childrenArr || []
              if (checkAll && children.length > 0) {
                //FormItem组件 显示提示
                children.forEach(item => {
                  const index = errors.findIndex(err => err.name === item.data.prop)
                  if (item.data.prop && item.data.prop !== true && ~index) {
                    item.setData({
                      errorMsg: errors[index].msg,
                      itemValue: model[item.data.prop]
                    })
                  }
                })
              }
            }
          }
          resolve(res)
        } catch (error) {
          reject({
            isPass: false,
            errorMsg: '校验出错，请检查数据格式是否有误！'
          })
        }
      })
    },
    setWatcherInstance(instance) {
      //设置页面实例，通知子组件开启表单数据监听
      setTimeout(() => {
        const children = this.data.childrenArr
        if (children && children.length > 0) {
          children.forEach(item => {
            item.setWatcherPageProp(instance)
          })
        }
      }, 50);
    },
    //结合FormItem组件进行校验时 是否开启即时校验
    immediateValidate(isOpen, rules = []) {
      this.data.isImmediate = isOpen;
      if (isOpen) {
        if (!rules || rules.length === 0) {
          rules = this.getFormItemRules()
        } else {
          rules = this.getMergeRules(rules)
        }
        this.data.formRules = rules || []
      }
      const children = this.data.childrenArr || []
      if (children.length > 0) {
        children.forEach(item => {
          item.immediateValidate(isOpen)
        })
      }
    },
    //校验
    immediateValidator(model, prop, rules) {
      return new Promise((resolve, reject) => {
        try {
          rules = rules || this.data.formRules
          rules = rules.filter(item => item.name === prop)
          let res = form.validation(model, rules);
          resolve(res)
        } catch (e) {
          reject({
            isPass: false,
            errorMsg: '校验出错，请检查数据格式是否有误！'
          })
        }
      })
    },
    clearValidate(props = []) {
      let arr = props;
      arr = !arr ? [] : arr
      if (typeof props === 'string') {
        arr = [props]
      }
      const children = this.data.childrenArr
      if (children && children.length > 0) {
        //清除指定字段的表单验证信息
        if (arr && arr.length > 0) {
          children.forEach(item => {
            if (item.data.prop && ~arr.indexOf(item.data.prop)) {
              item.setData({
                errorMsg: ''
              })
            }
          })
        } else {
          //清除所有字段的表单验证信息
          children.forEach(item => {
            item.setData({
              errorMsg: ''
            })
          })
        }
      }
    },
    /**
     * 验证具体的某个字段
     * @param {Array<string> ｜ String} props 字段key
     * @param {Array} rules 表单验证规则，当传null 或空数组时使用FormItem组件内rules
     * @param {Object} model 表单数据对象，不传则使用属性中model值
     */
    validateField(props, rules, model) {
      if (!rules || rules.length === 0) {
        rules = this.getFormItemRules()
      } else {
        rules = this.getMergeRules(rules)
      }
      const isString = typeof props === 'string';
      const formRules = rules.filter(item => props === item.name || (!isString && props
        .indexOf(item.name) !== -1));
      model = model || this.data.model
      return this.validate(model, formRules, true)
    },
    // 移除表单项
    uninstall(instance) {
      const children = this.data.childrenArr || []
      if (children.length > 0) {
        const index = children.findIndex(item => item === instance)
        if (index !== -1) {
          this.data.childrenArr.splice(index, 1)
        }
        const idx = this.data.concatRules.findIndex(ru => ru.name === instance.data.prop)
        if (idx !== -1) {
          this.data.concatRules.splice(idx, 1)
        }
      }
    }
  }
})